/**
* @Title: ObjectUtil.java
* @Package com.yly.utils
* @Description: 数据对象操作类
* @author zz
* @date 2013-12-19 下午1:47:27
* @version V1.0
*/
package com.yly.utils;

import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.beanutils.BeanUtils;

/**
 * @ClassName: ObjectUtil
 * @Description: 数据对象操作类
 * @author zz
 * @date 2013-12-19 下午1:47:27
 */
public class ObjectUtil {
	
	private static final String GET_NAME = "get";
	
	/**
	 * <p>Title: 设置线程中的本地对象</p>
	 * <p>Description: 设置线程中的本地对象</p>
	 * @param keys obj 容器对象
	 * @param keys 对象存放位置字符串（<b>.</b>）隔开
	 * @param value 存放的内容
	 */
	public static void set(Object obj, String keys, Object value) {
		if (!StrUtil.nil(keys)) {
			String[] keyArr = keys.split("\\.");
			set(obj, keyArr, value);
		}
	}

	/**
	 * <p>Title: 设置线程中的本地对象</p>
	 * <p>Description: 设置线程中的本地对象</p>
	 * @param keys obj 容器对象
	 * @param keyArr 对象存放位置数组
	 * @param value 存放的内容
	 */
	public static void set(Object obj,String[] keyArr, Object value) {
		if (keyArr != null && keyArr.length > 0) {
			set(obj, keyArr, value, 0);
		}
	}

	/**
	 * <p>Title: 递归设置对象属性</p>
	 * <p>Description: 递归设置对象属性，如果中途对象为空则用新建一个HashMap来补缺</p>
	 * @param obj 容器对象
	 * @param keyArr 存放的数组
	 * @param value 值
	 * @param i 当前属性索引
	 */
	@SuppressWarnings("rawtypes")
	public static void set(Object obj, String[] keyArr, Object value, int i) {
		String key = keyArr[i];
		if (i < keyArr.length - 1) {
			Object tmpObj = getValue(obj, key);
			if (tmpObj == null) {
				tmpObj = new HashMap();
				setValue(obj, key, tmpObj);
			}
			set(tmpObj, keyArr, value, ++i);
		} else {
			setValue(obj, key, value);
		}
	}
	
	/**
	 * <p>Title: 设置某对象的某属性的值</p>
	 * <p>Description: 设置某对象（obj）的某属性（key）的值（value）</p>
	 * @param obj 被设置的对象
	 * @param key 属性
	 * @param value 值
	 */
	private static void setValue(Object obj, String key, Object value) {
		try {
			BeanUtils.setProperty(obj, key, value);
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * <p>Title: 获得线程中的本地对象</p>
	 * <p>Description: 获得线程中的本地对象</p>
	 * @param obj 访问对象
	 * @param keyArr 对象存放位置字符串（<b>.</b>）隔开
	 * @return 获取的对象
	 */
	public static Object get(Object obj, String keys) {
		Object result = null;
		if (!StrUtil.nil(keys)) {
			String[] keyArr = keys.split("\\.");
			result = get(obj, keyArr);
		}
		return result;
	}

	/**
	 * <p>Title: 获得线程中的本地对象</p>
	 * <p>Description: 获得线程中的本地对象</p>
	 * @param obj 访问对象
	 * @param keyArr 对象存放位置数组
	 * @return 获取的对象
	 */
	public static Object get(Object obj, String[] keyArr) {
		Object result = null;
		if (obj != null && keyArr != null && keyArr.length > 0) {
			result = getValue(obj, keyArr, 0);
		}
		return result;
	}
	
	/**
	 * <p>Title: 获得执行obj下的属性值</p>
	 * <p>Description: 获取某对象（obj）下的某属性（keyArr[i]）内容. <b>主要用于递归</b></p>
	 * @param obj 访问对象
	 * @param keyArr 属性列表
	 * @param i 属性所在的索引
	 * @return 对象属性对应的值
	 */
	private static Object getValue(Object obj, String[] keyArr, int i) {
		Object result = getValue(obj, keyArr[i]);
		i++;
		if (i < keyArr.length) {
			if (result != null) {
				result = getValue(result, keyArr, i);
			}
		}
		return result;
	}

	/**
	 * <p>Title: 获取某对象下的某属性内容</p>
	 * <p>Description: 获取某对象（obj）下的某属性（key）内容</p>
	 * @param obj 访问对象
	 * @param key 对象属性
	 * @return 对象属性对应的值
	 */
	private static Object getValue(Object obj, String key) {
		Object result = null;
		Class<?> objClass = obj.getClass(); 
		try {
			if(obj instanceof Map){
				result = objClass.getMethod(GET_NAME, Object.class).invoke(obj, key);
			}else{
				String methodName = GET_NAME + StrUtil.firstCharToUpperCase(key);
				result = objClass.getMethod(methodName).invoke(obj);
			}
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (SecurityException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		} catch (NoSuchMethodException e) {
			e.printStackTrace();
		}
		return result;
	}
	
}
